#include "Clerc.h"

#include <iomanip>

#include "lib.h"

#include "ATL.h"

#include <algorithm>

using namespace std;
using namespace boost::assign;

const unsigned Clerc::nbrCompetences = 108;

const unsigned Clerc::nbrRestrictions = 20;

const unsigned Clerc::ppAlloues = 120;

/**
 * Les noms des sphères sont accentuées "à la LaTeX", afin de
 * simplifier la gestion des noms de dossiers.
 */
const vector<CompetenceClasse> Clerc::Comp = list_of
  (CompetenceClasse("Amélioration de la classe d'armure"           , 15))
  (CompetenceClasse("Arme symbolique"                              ,  5))
  (CompetenceClasse("Bonus au JS contre drain d'énergie"           ,  5))
  (CompetenceClasse("Bonus au PV de guerrier"                      , 15))
  (CompetenceClasse("Changement de forme"                          ,  0u, 100u, 1u, true ) )
  (CompetenceClasse("Combat à mains nues"                          , 15))
  (CompetenceClasse("Communication"                                , 10))
  (CompetenceClasse("Compétences diverses de combattant"           ,  5))
  (CompetenceClasse("Compétences diverses de magicien"             ,  5))
  (CompetenceClasse("Compétences diverses de roublard"             ,  5))
  (CompetenceClasse("Connaissance des alignements"                 , 15))
  (CompetenceClasse("Contrôle des esprits"                         , 25u, 200u, 2u ) )
  (CompetenceClasse("Dés de vie à 1d10"                            , 10))
  (CompetenceClasse("Détection des morts-vivants"                  , 10))
  (CompetenceClasse("Détection du mal"                             , 10))
  (CompetenceClasse("Durée de sorts accrue (1 sphère)"             , 10))
  (CompetenceClasse("Durée de sorts accrue (toutes)"               , 15))
  (CompetenceClasse("Empathie avec les animaux"                    , 10))
  (CompetenceClasse("Guérisseur expert"                            , 10))
  (CompetenceClasse("Identification des plantes et animaux (niv 8)",  5))
  (CompetenceClasse("Identification des plantes et animaux (niv 3)",  8))
  (CompetenceClasse("Immunité à la magie"                          , 15))
  (CompetenceClasse("Immunité aux charmes"                         ,  0u, 300u, 3u ) )
  (CompetenceClasse("Immunité aux maladies naturelles"             , 10))
  (CompetenceClasse("Imposition des mains"                         , 10))
  (CompetenceClasse("Incantation rapide"                           ,  5))
  (CompetenceClasse("Inspiration (+1)"                             ,  5))
  (CompetenceClasse("Inspiration (+2)"                             , 10))
  (CompetenceClasse("Langage secret"                               ,  5))
  (CompetenceClasse("Passage sans traces (niv 3)"                  ,  5))
  (CompetenceClasse("Passage sans traces (niv 1)"                  ,  7))
  (CompetenceClasse("Pouvoir divin"                                , 10u, 400u, 4u ) )
  (CompetenceClasse("Prêtre combattant"                            , 20))
  (CompetenceClasse("Purification de l'eau"                        ,  5))
  (CompetenceClasse("Repousser les morts-vivants"                  , 15))
  (CompetenceClasse("Résistance au drain d'énergie"                , 15))
  (CompetenceClasse("Résistance à l'électricité"                   ,  7))
  (CompetenceClasse("Résistance au feu"                            ,  7))
  (CompetenceClasse("Résistance au froid"                          ,  5))
  (CompetenceClasse("Sélection d'armes étendues"                   , 10))
  (CompetenceClasse("Suivants (niv 8)"                             ,  5))
  (CompetenceClasse("Suivants (niv 1)"                             , 10))
  (CompetenceClasse("TAc0 de guerrier"                             , 20))
  (CompetenceClasse("Talents de voleur"                            ,  0))
  // compétences -> 41
  (CompetenceClasse("Générale (min)", "Generale"                   ,  3))
  (CompetenceClasse("Animale (min)", "Animale"                     ,  5))
  (CompetenceClasse("Astrale (min)", "Astrale"                     ,  3))
  (CompetenceClasse("Chaos (min)", "Chaos"                         ,  5))
  (CompetenceClasse("Charme (min)", "Charme"                       ,  5))
  (CompetenceClasse("Climat (min)", "Climat"                       ,  3))
  (CompetenceClasse("Combat (min)", "Combat"                       ,  5))
  (CompetenceClasse("Conjuration (min)", "Conjuration"             ,  5))
  (CompetenceClasse("Création (min)", "Creation"                   ,  5))
  (CompetenceClasse("Divination (min)", "Divination"               ,  5))
  (CompetenceClasse("Elémentaire (min)", "Elementaire"             ,  8))
  (CompetenceClasse("Air (min)", "Air"                             ,  2))
  (CompetenceClasse("Eau (min)","Eau"                              ,  2))
  (CompetenceClasse("Feu (min)", "Feu"                             ,  3))
  (CompetenceClasse("Terre (min)", "Terre"                         ,  3))
  (CompetenceClasse("Garde (min)", "Garde"                         ,  3))
  (CompetenceClasse("Guerre (min)", "Guerre"                       ,  3))
  (CompetenceClasse("Loi (min)", "Loi"                             ,  5))
  (CompetenceClasse("Nécromancie (min)", "Necromancie"             ,  5))
  (CompetenceClasse("Nombres (min)", "Nombres"                     ,  5))
  (CompetenceClasse("Pensée (min)", "Pensee"                       ,  5))
  (CompetenceClasse("Protection (min)", "Protection"               ,  5))
  (CompetenceClasse("Soin (min)", "Soin"                           ,  5))
  (CompetenceClasse("Soleil (min)", "Soleil"                       ,  3))
  (CompetenceClasse("Temps (min)", "Temps"                         ,  5))
  (CompetenceClasse("Végétale (min)", "Vegetale"                   ,  5))
  (CompetenceClasse("Vigilance (min)", "Vigilance"                 ,  5))
  (CompetenceClasse("Voyageur (min)", "Voyageur"                   ,  3))
  // sphères mineures -> 68
  (CompetenceClasse("Générale (maj)", "Generale"                   ,  5))
  (CompetenceClasse("Animale (maj)", "Animale"                     , 10))
  (CompetenceClasse("Astrale (maj)", "Astrale"                     ,  6))
  (CompetenceClasse("Chaos (maj)", "Chaos"                         ,  8))
  (CompetenceClasse("Charme (maj)", "Charme"                       , 10))
  (CompetenceClasse("Climat (maj)", "Climat"                       , 10))
  (CompetenceClasse("Combat (maj)", "Combat"                       , 10))
  (CompetenceClasse("Conjuration (maj)", "Conjuration"             , 10))
  (CompetenceClasse("Création (maj)", "Creation"                   , 10))
  (CompetenceClasse("Divination (maj)", "Divination"               , 10))
  (CompetenceClasse("Elémentaire (maj)", "Elementaire"             , 20))
  (CompetenceClasse("Air (maj)", "Air"                             ,  5))
  (CompetenceClasse("Eau (maj)", "Eau"                             ,  5))
  (CompetenceClasse("Feu (maj)", "Feu"                             ,  8))
  (CompetenceClasse("Terre (maj)", "Terre"                         ,  8))
  (CompetenceClasse("Garde (maj)", "Garde"                         ,  5))
  (CompetenceClasse("Guerre (maj)", "Guerre"                       ,  5))
  (CompetenceClasse("Loi (maj)", "Loi"                             ,  8))
  (CompetenceClasse("Nécromancie (maj)", "Necromancie"             , 10))
  (CompetenceClasse("Nombres (maj)", "Nombres"                     , 10))
  (CompetenceClasse("Pensée (maj)", "Pensee"                       , 10))
  (CompetenceClasse("Protection (maj)", "Protection"               , 10))
  (CompetenceClasse("Soin (maj)", "Soin"                           , 10))
  (CompetenceClasse("Soleil (maj)", "Soleil"                       ,  5))
  (CompetenceClasse("Temps (maj)", "Temps"                         , 10))
  (CompetenceClasse("Végétale (maj)", "Vegetale"                   , 10))
  (CompetenceClasse("Vigilance (maj)", "Vigilance"                 , 10))
  (CompetenceClasse("Voyageur (maj)", "Voyageur"                   ,  5))
  (CompetenceClasse("Abjuration (mage)"                            , 25))
  (CompetenceClasse("Altération (mage)", "Alteration_mage"         , 25))
  (CompetenceClasse("Conjuration - Convocation (mage)", "Conjuration_mage" , 25))
  (CompetenceClasse("Enchantement - Charme (mage)", "Enchantement_mage"    , 25))
  (CompetenceClasse("Divination (mage)", "Divination_mage"         , 25))
  (CompetenceClasse("Illusion - Fantasme (mage)", "Illusion_mage"  , 25))
  (CompetenceClasse("Invocation - Evocation (mage)", "Invocation_mage"     , 25))
  (CompetenceClasse("Nécromancie (mage)", "Necromancie_mage"       , 25));
  // sphères majeures -> 105

const vector<CompetenceClasse> Clerc::Restric = list_of
  (CompetenceClasse("Cérémonial"                                  ,  5))
  (CompetenceClasse("Choix des armes restreint"                   ,  5))
  (CompetenceClasse("Choix de sorts restreint"                    ,  5))
  (CompetenceClasse("Dés de vie à 1d6"                            , 10))
  (CompetenceClasse("Dés de vie à 1d4"                            , 20))
  (CompetenceClasse("Difficultés de mémorisation"                 ,  5))
  (CompetenceClasse("Fanatisme"                                   ,  5))
  (CompetenceClasse("Incantation longue"                          ,  5))
  (CompetenceClasse("Lim : potions, huiles et parchemins"         ,  5))
  (CompetenceClasse("Lim : anneau, de bâton, bâtonnet et baguette",  5))
  (CompetenceClasse("Lim : armes et armures magiques"             ,  5))
  (CompetenceClasse("Limitation à la maille"                      ,  5))
  (CompetenceClasse("Limitation au cuir clouté"                   , 10))
  (CompetenceClasse("Manque de discrétion"                        ,  5))
  (CompetenceClasse("Pas d'armes"                                 , 15))
  (CompetenceClasse("Pas d'armure"                                , 15))
  (CompetenceClasse("Progression ralentie"                        , 15))
  (CompetenceClasse("Sorts dangereux"                             , 10))
  (CompetenceClasse("Tabou"                                       ,  2))
  (CompetenceClasse("Talisman"                                    ,  8));

const vector< Prerequis > Clerc::Limites = list_of
  (Prerequis(4, 9));

const set< string > Clerc::RacesAdmises = list_of
  ( "Humain" ) ( "Demi-Elfe" ) ( "Demi-Ogre" ) ( "Demi-Orque" )
  ( "Elfe" ) ( "Gnome" ) ( "Hobbit" ) ( "Nain" );

const vector< CompetenceClasse > Clerc::ChgtForme = list_of
  (CompetenceClasse("Normal - niv 7", 15))
  (CompetenceClasse("Dès niv 6", 17)) (CompetenceClasse("Dès niv 5", 19))
  (CompetenceClasse("Dès niv 4", 21)) (CompetenceClasse("Dès niv 3", 23))
  (CompetenceClasse("Dès niv 2", 25)) (CompetenceClasse("Dès niv 1", 27));

const vector< CompetenceClasse > Clerc::CtrlEsprit = list_of
  (CompetenceClasse("Esprits animaux", 5))
  (CompetenceClasse("Esprits des morts", 5)) 
  (CompetenceClasse("Esprits de la nature", 5));

const vector< CompetenceClasse > Clerc::ImmuCharme =  list_of
  (CompetenceClasse("Créatures extraplanaires", 5))
  (CompetenceClasse("Créatures sylvestres", 5))
  (CompetenceClasse("Créatures végétales", 5))
  (CompetenceClasse("Magiciens", 5))
  (CompetenceClasse("Morts-vivants", 5))
  (CompetenceClasse("Dès niv 6", 1)) (CompetenceClasse("Dès niv 5", 2)) (CompetenceClasse("Dès niv 4", 3))
  (CompetenceClasse("Dès niv 3", 4)) (CompetenceClasse("Dès niv 2", 5)) (CompetenceClasse("Dès niv 1", 6));

const vector< CompetenceClasse > Clerc::PouvDivins = list_of
  (CompetenceClasse("Sort de prêtre niv 1", 1)) (CompetenceClasse("Sort de prêtre niv 2", 2))
  (CompetenceClasse("Sort de prêtre niv 3", 3)) (CompetenceClasse("Sort de prêtre niv 4", 4)) 
  (CompetenceClasse("Sort de prêtre niv 5", 5))
  (CompetenceClasse("Sort de mage niv 1", 2)) (CompetenceClasse("Sort de mage niv 2", 4))
  (CompetenceClasse("Sort de mage niv 3", 6)) (CompetenceClasse("Sort de mage niv 4", 8)) 
  (CompetenceClasse("Sort de mage niv 5", 10)) 
  (CompetenceClasse("1x / jour", 5)) (CompetenceClasse("2x / jour", 6)) (CompetenceClasse("3x / jour", 7))
  (CompetenceClasse("Permanent", 10));

/** Constructeur usuel.
 * Permet la construction d'un clerc de A à Z, càd on détermine ici
 * les restrictions, puis les compétences.
 *
 * @param[in] xp le nombre de pts d'expérience du Clerc.
 * @param[in] trait les traits du Clerc, le 7ème contient le score de
 * force exceptionnelle, fixé à 0 si non applicable.
 * @param[in,out] PP nombre de points de personnage (PP) à disposition
 * pour la création du Clerc.
 * @param[in] race nom de la race du personnage.
 */
Clerc::Clerc(unsigned xp, const vector< unsigned >& trait,
	     unsigned& PP, const string& race)
  : Classe( xp, Pretres, "Clerc" )
{
  //NomClasse = "Clerc";
  NombrePPsAlloues = ppAlloues;
  PP += NombrePPsAlloues;

  NombreTotalCompetences  = nbrCompetences;
  NombreTotalRestrictions = nbrRestrictions;
  NombreTotalEnsembles    = 0;
  NombreMaxCompetences    = 0;
  ListesCompetences       = list_of< vector< CompetenceClasse > >( Comp )( ChgtForme )
    ( CtrlEsprit )( ImmuCharme )( PouvDivins );
  ListeRestrictions       = Restric;
  PrerequisClasse         = list_of< vector< Prerequis > >( Limites );
  RacesAdmisesClasse      = list_of< set< string > >( RacesAdmises );

  blank() << "********************************************************" << endmsg;
  blank() << "Création d'un clerc" << endmsg << endmsg;

  construitClasse( PP, trait, race );

  blank() << endmsg << setfill('*') << setw(56) << '*' << setfill(' ')
	      << endmsg;
  calculNiveau();
  calculNivMag();
}

/** Constructeur simplifié.
 * Permet de construire un Clerc lors de la lecture d'un ficier xml.
 *
 * @param[in] xp le nombre de pts d'expérience du Clerc.
 * @param[in] trait les traits du Clerc, le 7ème contient le score de
 * force exceptionnelle, fixé à 0 si non applicable.
 * @param[in] race nom de la race du personnage.
 */
Clerc::Clerc( unsigned xp )
  : Classe( xp, Pretres, "Clerc" )
{
  //NomClasse = "Clerc";
  NombrePPsAlloues = ppAlloues;

  NombreTotalCompetences  = nbrCompetences;
  NombreTotalRestrictions = nbrRestrictions;
  NombreTotalEnsembles    = 0;
  NombreMaxCompetences    = 0;
  ListesCompetences       = list_of< vector< CompetenceClasse > >( Comp )( ChgtForme )
    ( CtrlEsprit )( ImmuCharme )( PouvDivins );
  ListeRestrictions       = Restric;
  PrerequisClasse         = list_of< vector< Prerequis > >( Limites );
  RacesAdmisesClasse      = list_of< set< string > >( RacesAdmises );

  calculNiveau();
  calculNivMag();
}

/** Constructeur pour le mode graphique.
 * Permet de construire une instance de Clerc avec le contenu minimal,
 * le nombre de points d'expériences et les capacités étant
 * déterminées après la déclaration.
 *
 * @param[in] UI contrôle, est présent pour des raisons historiques.
 */
Clerc::Clerc( const bool& UI )
  : Classe( 0,  Pretres, "Clerc" )
{
  if (!UI)
    {
      error() << "Création du personnage impossible" << endmsg;
      exit(1);
    }

  //NomClasse = "Clerc";
  NombrePPsAlloues = ppAlloues;

  NombreTotalCompetences  = nbrCompetences;
  NombreTotalRestrictions = nbrRestrictions;
  NombreTotalEnsembles    = 0;
  NombreMaxCompetences    = 0;
  ListesCompetences       = list_of< vector< CompetenceClasse > >( Comp )( ChgtForme )
    ( CtrlEsprit )( ImmuCharme )( PouvDivins );
  ListeRestrictions       = Restric;
  PrerequisClasse         = list_of< vector< Prerequis > >( Limites );
  RacesAdmisesClasse      = list_of< set< string > >( RacesAdmises );

  calculNiveau();
  calculNivMag();
}

/**
 * Constructeur de "copie", destiné à être utilisé depuis MetaClasse.
 *
 * @param[in] ptr pointeur sur un objet de type Classe (MetaClasse en
 * fait).
 */
Clerc::Clerc(Classe *ptr)
  : Classe( *ptr )
{
  NomClasse = "Clerc";
  NombrePPsAlloues = ppAlloues;

  NombreTotalCompetences  = nbrCompetences;
  NombreTotalRestrictions = nbrRestrictions;
  NombreTotalEnsembles    = 0;
  NombreMaxCompetences    = 0;
  ListesCompetences       = list_of< vector< CompetenceClasse > >( Comp )( ChgtForme )
    ( CtrlEsprit )( ImmuCharme )( PouvDivins );
  ListeRestrictions       = Restric;
  PrerequisClasse         = list_of< vector< Prerequis > >( Limites );
  RacesAdmisesClasse      = list_of< set< string > >( RacesAdmises );

  calculNiveau();
  calculNivMag();
}

Clerc::~Clerc()
{}

void Clerc::calculNiveau()
{
  if (XP < 13000)
    {
      unsigned i;
      for (i = 0; i < 3; i++)
	{
	  if (XP < (unsigned) 1500 * puissance(2, i))
	    break;
	}
      Niveau = i + 1;
    }
  else if (XP < 27500)
    Niveau = 5;
  else if (XP < 55000)
    Niveau = 6;
  else if (XP < 110000)
    Niveau = 7;
  else if (XP < 225000)
    Niveau = 8;
  else
      Niveau = (XP - 225000) / 225000 + 9;
}

// /**
//  * Il faut faire attention aux accents...
//  * @see afficheAccent
//  */
// void Clerc::afficher_stats(ostream& os)
// {
//   os << "Classe : Clerc" << endmsg;
//   for (unsigned i(0); i<6; i++)
//     os << Caracteristiques[i] << ' ' << Traits[i] << endmsg;
//   for (unsigned i(0); i<Competences.size(); i++)
//     {
//       if (Competences[i] >= nbrCompetences)
// 	os << afficheAccent(Restric[Competences[i]-nbrCompetences].Comp)
// 		    << endmsg;
//       else
// 	os << afficheAccent(Comp[Competences[i]].Comp) << endmsg;
//     }
// }

// void Clerc::appliquerModif(const string& type)
// {}

// void Clerc::augmenterTalents(const unsigned& bonus, const bool& lvl_up)
// {}

void Clerc::js(unsigned *tab) const
{
  /*Debug::*/empileNiveau( &fonction );
  //DebugLevelType etat_precedent(dout.getLevel());
  //dout.setLevel(fonction);
  *(tab + 0) = 10; // Paralysie, Poison ou Mort magique
  *(tab + 1) = 14; // Bâton, batonnet baguette
  *(tab + 2) = 13; // Pétrification ou Métamorphose
  *(tab + 3) = 16; // Souffles
  *(tab + 4) = 15; // Sorts

  debug() << "Niveau = " << Niveau << endmsg;
  
  unsigned cat;
  if (Niveau <= 3)
    cat = 0;
  else if (Niveau <= 6)
    cat = 1;
  else if (Niveau <= 9)
    cat = 3;
  else if (Niveau <= 12)
    cat = 4;
  else if (Niveau <= 15)
    cat = 5;
  else if (Niveau <= 18)
    cat = 6;
  else
    cat = 8;

  *(tab + 0) -= cat;
  *(tab + 1) -= cat;
  *(tab + 2) -= cat;
  *(tab + 3) -= cat;
  *(tab + 4) -= cat;
  /*Debug::*/depileNiveau();//dout.setLevel(etat_precedent);
}

/**
 * Si Classe::elementaire a la valeur DEBUG, la distinction Compétence /
 * Restriction est affichée.
 */
// string Clerc::getCompetence(const unsigned& i) const
// {
//   /*Debug::*/empileNiveau( &elementaire );
//   //DebugLevelType etat_precedent(dout.getLevel());
//   //dout.setLevel(elementaire);
//   if (getComp(i) < nbrCompetences)
//     {
//       debug() << "comp " << getComp(i) << " => comp" << endmsg;
//       /*Debug::*/depileNiveau();//dout.setLevel(etat_precedent);
//       return Comp[getComp(i)].Comp;
//     }
//   else
//     {
//       debug() << "comp " << getComp(i) << " => res" << endmsg;
//       /*Debug::*/depileNiveau();//dout.setLevel(etat_precedent);
//       return Restric[getComp(i)-nbrCompetences].Comp;
//     }
// }

unsigned Clerc::calculeTAc0() const
{
  unsigned mod_niveau(2 * ((Niveau - 1) / 3));

  return 20 - mod_niveau;
}

void Clerc::calculNivMag()
{
  if (Niveau < 16)
    NiveauMagique = (Niveau + 1) / 2;
  else
    NiveauMagique = 7;
}

/**
 * Les sorts disponibles pour un Clerc sont donnés par son niveau et
 * les sphères auquelles il a accès.
 *
 * La variable Classe::fonction permet d'afficher :
 *
 * FUNC  : le nom du fichier qui va être écrit
 *
 * LINFO : la vérification que la compétence est bien une sphère, ou une
 * école de magie
 *
 * LFUNC : gestion des sphères élémentaires et des accents
 *
 * DEBUG : ouverture du fichier, 
 * 
 */
void Clerc::ecrireSorts( const string& nom_fichier, const bool& ecrase,
			 const unsigned& sagesse ) const
{
  /*Debug::*/empileNiveau( &fonction );
  func() << "Clerc::ecrireSorts -> début" << endmsg;
  ofstream sortie;
  string nomComplet, nomFichier;
  func() << "A écrire : " << nom_fichier << endmsg;

  if (ecrase)
    /*
     * Ecrase l'éventuel contenu du fichier
     */
    {
      sortie.open(nom_fichier.c_str());
      debug() << "Ouverture                [ OK ]" << endmsg;
    }
  else
    /*
     * Alors on ouvre le fichier de telle sorte à écrire à la suite
     */
    {
      sortie.open(nom_fichier.c_str(), ios::app);
      debug() << "Ouverture                [ OK ]" << endmsg;
    }

  sortie << "\\section*{Sorts disponibles - Prêtre}" << endl;

  vector< unsigned > vec;

  sortsParNiveau( vec, sagesse );

  sortie << "\\begin{center}" << endl 
	 << "\\begin{tabular*}{10cm}{@{\\extracolsep{\\fill}} l r}"
	 << endl << "\\multicolumn{2}{c}{Nombre de sorts par jour} \\\\"
	 << "\\hline \\\\ \\vspace{1mm}" << endl;
  for (unsigned i(0); i < NiveauMagique; i++)
    sortie << "Niveau " << i+1 << " & " << vec[ i ] << " \\\\" << endl;
  sortie << "\\end{tabular*}" << endl << "\\end{center}" << endl;

  unsigned taille( tailleCompetences() );
  size_t loc;

  for (unsigned i(0); i < taille; i++)
    {
      if ( numCompetence(i) > 2)
	{
	  /*
	   * Ne pas oublier le 'true', pour garder la syntaxe LaTeX !
	   * sinon on a les accents écrits "en dur" et on ne peut plus
	   * rien faire pour rattraper le coup!
	   */
	  nomFichier = nomCompetence( i, true );
	  nomComplet = nomCompetence( i );
	  linfo() << "Vérification sphère : " << nomComplet << endmsg;
	  loc = nomComplet.find(" (m", 0);
	  if (loc == string::npos)
	    {
	      lfunc() << "Pas une sphère..." << endmsg;
	      continue;
	    }
	  loc = nomComplet.find("mentaire", 0);
	  if (loc != string::npos)
	    {
	      lfunc() << "Sphère Elémentaire..." << endmsg;
	      continue;
	    }
	  
	  loc = nomComplet.find("mage", 0);
	  if (loc != string::npos)
	    linfo() << "Ecole de magie" << endmsg;

	  for ( unsigned j(1); j <= NiveauMagique; j++ )
	    {
	      if ( numCompetence( i ) < 68 && j > 3)
		/*
		 * Accès mineur => jusqu'au lvl 3 uniquement!
		 */
		break;
	      sortie << "\\input{../../Sorts-clerc/" << nomFichier
		/*supprimeAccents(nomFichier)*/
		     << "-"  << ecrireString(j) << ".inc.tex}" << endl;
	      
	    }
	
	}
    }

  sortie.close();
  func() << "Clerc::ecrireSorts -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

void Clerc::sortsParNiveau( vector< unsigned >& sorts,
			    const unsigned& sagesse ) const
{
  /*Debug::*/empileNiveau( &fonction );

  vector< unsigned > tmp( 7, 0 );
  func() << "Nbr de niveaux de sort = " << NiveauMagique << endmsg;

  switch(Niveau)
    {
    case 1:
      tmp[0] = 1;
      break;
    case 2:
      tmp[0] = 2;
      break;
    case 3:
      tmp[0] = 2;
      tmp[1] = 1;
      break;
    case 4:
      tmp[0] = 3;
      tmp[1] = 2;
      break;
    case 5:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 1;
      break;
    case 6:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 2;
      break;
    case 7:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 2;
      tmp[3] = 1;
      break;
    case 8:
      tmp[0] = 3;
      tmp[1] = 3;
      tmp[2] = 3;
      tmp[3] = 2;
      break;
    case 9:
      tmp[0] = 4;
      tmp[1] = 4;
      tmp[2] = 3;
      tmp[3] = 2;
      tmp[4] = 1;
      break;
    case 10:
      tmp[0] = 4;
      tmp[1] = 4;
      tmp[2] = 3;
      tmp[3] = 3;
      tmp[4] = 2;
      break;
    case 11:
      tmp[0] = 5;
      tmp[1] = 4;
      tmp[2] = 4;
      tmp[3] = 3;
      tmp[4] = 2;
      if (sagesse >= 17)
      tmp[5] = 1;
      break;
    case 12:
      tmp[0] = 6;
      tmp[1] = 5;
      tmp[2] = 5;
      tmp[3] = 3;
      tmp[4] = 2;
      if (sagesse >= 17)
      tmp[5] = 2;
      break;
    case 13:
      tmp[0] = 6;
      tmp[1] = 6;
      tmp[2] = 6;
      tmp[3] = 4;
      tmp[4] = 2;
      if (sagesse >= 17)
      tmp[5] = 2;
      break;
    case 14:
      tmp[0] = 6;
      tmp[1] = 6;
      tmp[2] = 6;
      tmp[3] = 5;
      tmp[4] = 3;
      if (sagesse >= 17)
      tmp[5] = 2;
      if (sagesse >= 18)
      tmp[6] = 1;
      break;
    case 15:
      tmp[0] = 6;
      tmp[1] = 6;
      tmp[2] = 6;
      tmp[3] = 6;
      tmp[4] = 4;
      if (sagesse >= 17)
	tmp[5] = 2;
      if (sagesse >= 18)
	tmp[6] = 1;
      break;
    case 16:
      tmp[0] = 7;
      tmp[1] = 7;
      tmp[2] = 7;
      tmp[3] = 6;
      tmp[4] = 4;
      if (sagesse >= 17)
	tmp[5] = 3;
      if (sagesse >= 18)
	tmp[6] = 1;
      break;
    case 17:
      tmp[0] = 7;
      tmp[1] = 7;
      tmp[2] = 7;
      tmp[3] = 7;
      tmp[4] = 5;
      if (sagesse >= 17)
	tmp[5] = 3;
      if (sagesse >= 18)
	tmp[6] = 2;
      break;
    case 18:
      tmp[0] = 8;
      tmp[1] = 8;
      tmp[2] = 8;
      tmp[3] = 8;
      tmp[4] = 6;
      if (sagesse >= 17)
	tmp[5] = 4;
      if (sagesse >= 18)
	tmp[6] = 2;
      break;
    case 19:
      tmp[0] = 9;
      tmp[1] = 9;
      tmp[2] = 8;
      tmp[3] = 8;
      tmp[4] = 6;
      if (sagesse >= 17)
	tmp[5] = 4;
      if (sagesse >= 18)
	tmp[6] = 2;
      break;
    default:
      tmp[0] = 9;
      tmp[1] = 9;
      tmp[2] = 9;
      tmp[3] = 8;
      tmp[4] = 7;
      if (sagesse >= 17)
	tmp[5] = 5;
      if (sagesse >= 18)
	tmp[6] = 2;
      break;
    }

  sorts.assign( tmp.begin(), tmp.end() );
  sorts.resize( NiveauMagique );

  unsigned compteur1(0), compteur2(0), compteur3(0), compteur4(0), i;

  if (sagesse >= 13 && sagesse < 18)
    {
      compteur1 = (sagesse - 11) / 2;
      compteur2 = (sagesse - 12) / 2;
    }
  else if (sagesse >= 18 && sagesse < 19)
    {
      compteur1 = sagesse - 14;
      compteur2 = sagesse - 16;
    }
  else if (sagesse >= 19 && sagesse < 23)
    {
      compteur1 = (sagesse + 1) / 2 - 6;
      compteur2 = sagesse / 2 - 6;
      compteur3 = sagesse - 18;
    }
  else
    {
      compteur1 = (sagesse + 1) / 2 - 6;
      compteur2 = sagesse / 2 - 6;
      compteur3 = sagesse - 19;
      compteur4 = 1;
    }

  for (i = 0; i < compteur1; i++)
    {
      if (i == NiveauMagique)
	break;
      sorts[i]++;
    }
  for (i = 0; i < compteur2; i++)
    {
      if (i == NiveauMagique)
	break;
      sorts[i]++;
    }
  for (i = 0; i < compteur3; i++)
    {
      if (i == NiveauMagique)
	break;
      sorts[i]++;
    }
  for (i = 0; i < compteur4; i++)
    {
      if (i == NiveauMagique)
	break;
      sorts[i]++;
    }

  /*Debug::*/depileNiveau();//dout.setLevel(etat_precedent);  
}

/**
 * Permet de gérer les compétences martiales, càd lesquelles sont accessibles
 * à quel coût.
 *
 * Un Clerc peut prendre un arme réservée au Clerc pour 3 pp, ou alors une
 * arme de Guerrier pour 4 pp.
 */
void Clerc::prixAcces(map<string, unsigned>*& Map) const
{
  /*Debug::*/empileNiveau( &fonction );
  func() << "Clerc::prixAcces -> début" << endmsg;

  ExtraireClef< string, unsigned > extraitStr;
  vector< string > clefs( Map -> size() );
  EcrireElementConteneur< string, FlotMessage > ecrireStr( &lfunc() );

  map<string, unsigned>::const_iterator mapIt, mapBegin(Map -> begin()),
    mapEnd(Map -> end());
  
  transform( mapBegin, mapEnd, clefs.begin(), extraitStr );
  for_each( clefs.begin(), clefs.end(), ecrireStr );

//   for (mapIt = mapBegin; mapIt != mapEnd; mapIt++)
//        lfunc() << mapIt -> first << endmsg;
 
  mapIt = Map -> find("Clerc");
  if ((mapIt != mapEnd && mapIt -> second > 3) || mapIt == mapEnd)
    Map -> operator[]("Clerc")    = 3;
  mapIt = Map -> find("Guerrier");
  if ((mapIt != mapEnd && mapIt -> second > 4) || mapIt == mapEnd)
    Map -> operator[]("Guerrier") = 4;
  
  func() << "Clerc::prixAccess -> fin" << endmsg;
  /*Debug::*/depileNiveau();
}

bool Clerc::forceExceptionnelle() const
{
  return ( std::find( Competences.begin(), Competences.end(), 38 )
	   != Competences.end() );  
}

unsigned Clerc::aSpecialisation() const
{
  return 0;
}
